using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Map2
{
    /// <summary>
    /// This class is using to define a buiding on the map
    /// It has a list of points which defines the corners of the building
    /// The GraphicsPath is used to draw the building on the map
    /// </summary>
    class Building
    {
        private List<Point> points = new List<Point>();
        private bool selected = false;

        /// <summary>
        /// This constructor just gives us a new entity of buiding, without any parameters
        /// </summary>
        public Building() { }

        /// <summary>
        /// This constructor creates a new buiding with an existing array of points
        /// </summary>
        /// <param name="points">These points are going to be save in the list of points of the building</param>
        public Building(Point[] points)
        {

            foreach (Point p in points)
            {
                this.points.Add(p);
            }
        }

        /// <summary>
        /// This method add a new point at the end of the list of point of our building
        /// </summary>
        /// <param name="p">p is the new point to add at our building</param>
        public void addPoint(Point p)
        {
            points.Add(p);
        }

        /// <summary>
        /// This method draw all the points and fill the polygon on an existing Graphics
        /// </summary>
        /// <param name="g">This Graphics already exist and we draw on it</param>
        public void draw(Graphics g)
        {
            if (points.Count > 2)
            {
                g.FillPolygon(Brushes.MidnightBlue,points.ToArray());
            }
            foreach (Point p in points)
                g.DrawRectangle(new Pen(Color.Red, 3), p.X - 3, p.Y - 3, 6, 6);
        }

        /// <summary>
        /// This method return true if this building is under the position define by <paramref name="x"/> and <paramref name="y"/>
        /// </summary>
        /// <param name="x">The abscisse of the point</param>
        /// <param name="y">The ordinate of the point</param>
        /// <returns>True if the building is under the position</returns>
        public bool isInPosition(int x, int y)
        {
            //The point is in the polygon, if the number of intersection between the "demi-droite"
            //and the polygon is unpair
            int nbInt = 0;
            int nbPts = points.Count;
            for (int i = 0; i < nbPts; i++)
            {
                if ((points[(i + 1) % nbPts].X - points[i].X) != 0)
                {
                    if (x > Math.Min(points[i].X, points[(i + 1) % nbPts].X) && x < Math.Max(points[i].X, points[(i + 1) % nbPts].X))
                    {//L abscisse du point doit etre compris entre les abscisses des deux points de la droite
                        float diffY = (points[(i + 1) % nbPts].Y - points[i].Y);
                        float diffX = (points[(i + 1) % nbPts].X - points[i].X);
                        float coeff = (float)(diffY / diffX);
                        if (y < coeff * (x - points[i].X) + points[i].Y)    //La demi droite part vers le haut, on cherche l intersection
                            nbInt++;
                    }
                    else if (x == points[i].X && y < points[i].Y)   //La demi droite passe par un des points
                        nbInt++;

                }
            }
            if (nbInt % 2 == 0)
                return false;
            return true;
            //return gp.IsVisible(x, y);
        }

        /// <summary>
        /// This method is closed to <c>isDowntheMouse</c> but we are looking for a point instead off the whole building
        /// </summary>
        /// <param name="x">The abscisse of the point</param>
        /// <param name="y">The ordinate of the point</param>
        /// <returns>True if the point is at the position (x+-3,y+-3)</returns>
        public Point pointDowntheMouse(int x, int y)
        {
            foreach (Point p in points)
            {
                if (Math.Abs(p.X - x) <= 3 && Math.Abs(p.Y - y) <= 3)
                    return p;
            }
            return Point.Empty;
        }

        /// <summary>
        /// This method translate the whole building by <paramref name="x"/> horizontal and <paramref name="y"/> vertical
        /// </summary>
        /// <param name="x">Horizontal translate</param>
        /// <param name="y">Vertical Translate</param>
        public void translate(int x, int y)
        {
            Point[] p = points.ToArray();
            points.RemoveRange(0, points.Count);
            for (int i = 0; i < p.Length; i++)
            {
                p[i].X += x;
                p[i].Y += y;
                points.Add(p[i]);
            }


        }

        /// <summary>
        /// This method moves only one point of the building
        /// </summary>
        /// <param name="p">the point we want to move</param>
        /// <param name="x">horizontal translate</param>
        /// <param name="y">vertical translate</param>
        public void movePoint(Point p, int x, int y)
        {
            int index = points.IndexOf(p);
            points.Remove(p);
            p.X += x;
            p.Y += y;
            points.Insert(index, p);
        }

        /// <summary>
        /// This method said us if the building is selected
        /// </summary>
        /// <param name="select"></param>
        public void setSelected(bool select)
        {
            selected = select;
        }

        public List<Point> getPoints()
        {
            return points;
        }

    }
}
